import java.util.AbstractCollection;
import java.util.EmptyStackException;
import java.util.NoSuchElementException;

/**
 * The Stack class represents a LIFO-stack of objects. When a stack is first
 * created, it contains no items. Work with <code> null </code>.
 * 
 * @author Mironoff Michail
 */

public class ArrayStack extends AbstractCollection<Integer> {
	private Integer[] arr = {};
	private int count = 0;

	/**
	 * Tests if this stack is empty. Works in O(1) time.
	 * 
	 * @return <code>true</code> if and only if this stack contains no items;
	 *         <code>false</code> otherwise.
	 */
	public boolean isEmpty() {
		return (count == 0);
	}

	/**
	 * Looks at the object at the top of this stack without removing it from the
	 * stack. Works in O(1) time.
	 * 
	 * @return the object at the top of this stack.
	 * @throws java.util.EmptyStackException
	 *             if this stack is isEmpty.
	 */
	public Integer peek() {
		if (count != 0) {
			return arr[count - 1];
		} else
			throw new EmptyStackException();

	}

	/**
	 * Removes the object at the top of this stack and returns that object as
	 * the value of this function. Works in O(1) time.
	 * 
	 * @return the object at the top of this stack.
	 * @throws java.util.EmptyStackException
	 *             if this stack is isEmpty.
	 */
	public Integer pop() {
		if (count != 0) {
			count--;
			Integer a = arr[count];
			arr[count] = null;
			return a;

		} else
			throw new EmptyStackException();
	}

	/**
	 * Pushes an item onto the top of this stack. Works in O(1) time
	 * 
	 * @param item
	 *            the item to be pushed onto this stack.
	 * @return the <code>item</code> argument
	 */
	public Integer push(Integer item){
                if(count==arr.length)
                {
                        count++;
                        Integer[] arrcopy=new Integer[count * 2];
                        System.arraycopy(arr, 0, arrcopy, 0, (count - 1));
                        arrcopy[count-1]=item;
                        arr=arrcopy;
                }
                else
                {
                        arr[count]=item;
                        count++;                        
                }
				return item;
        }

	/**
	 * Removes all of the elements from this stack. The stack will be empty
	 * after this call returns. Works in O(N) time.
	 */
	public void clear() {
		while (count != 0)
			pop();
	}

	/**
	 * Returns the 1-based position where an object is on this stack. If the
	 * object <code>item</code> occurs as an item in this stack, this method
	 * returns the distance from the top of the stack of the occurrence nearest
	 * the top of the stack; the topmost item on the stack is considered to be
	 * at distance <code>1</code>. The equals method is used to compare
	 * <code>item</code> to the items in this stack. Works in O(N) time.
	 * 
	 * @param item
	 *            the desired object.
	 * @return the 1-based position from the top of the stack where the object
	 *         is located; the return value <code>-1</code> indicates that the
	 *         object is not on the stack.
	 */
	public int search(Integer item) {
		int i = count;
		while (i != 0) {
			if (arr[i - 1] == null) {
				if (item == null)
					return count - i;
			} else if (arr[i - 1].equals(item))
				return count - i;
			i--;
		}
		return -1;
	}

	/**
	 * Returns the number of components in this stack. Works in O(1) time.
	 * 
	 * @return the number of components in this stack.
	 */
	@Override
	public int size() {
		return count;
	}

	/**
	 * Returns a string representation of stack. It begins from the bottom of
	 * the stack. Works in O(N) time.
	 * 
	 * @return a string representation of stack.
	 */
	public String toString() {
		StringBuilder s = new StringBuilder();
		s.append("[");
		for (int i = 0; i < count; i++) {
			s.append(arr[i]);
			if (count - i > 1) {
				s.append(", ");
			}
		}
		s.append("]");
		return s.toString();
	}

	@Override
	public java.util.Iterator<Integer> iterator() {
		return new Iterator();
	}

	public class Iterator implements java.util.Iterator<Integer> {

		private int iter;

		public Iterator() {
			this.iter = -1;

		}

		/**
		 * Returns true if the iteration has more elements.   ﻿ ﻿ *
		 * @return * <code>true</code> if the iteration has more elements
		 */
		@Override
		public boolean hasNext() {
			return (ArrayStack.this.size() != iter + 1);
		}

		/**
		 * Returns the next element in the iteration.
		 * 
		 * @return the next element in the iteration
		 * @throws java.util.NoSuchElementException
		 *             - if the iteration has no more elements
		 */
		@Override
		public Integer next() {
			if (hasNext()) {
				return arr[++this.iter];
			} else
				throw new NoSuchElementException();

		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException(
					"This operation isn't supported in this collection");
		}

	}

}